﻿using Core;
using Core.Infrastructure;
using Core.Plugins;
using Infrastructure.Mvc.Routing;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;

namespace BP.Plugin.Swagger;

internal class BoilerplateStartup : IBoilerplateStartup, IRouteProvider
{
    public int Order => 2001;

    public int Priority => Order;

    public void Configure(IApplicationBuilder application)
    {
        application.UseSwagger();
        application.UseSwaggerUI();
    }

    public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "开发框架", Version = "v1.0" });

            c.CustomOperationIds(apiDesc =>
            {
                // 1. 处理传统控制器
                if (apiDesc.ActionDescriptor is ControllerActionDescriptor controllerAction)
                {
                    return $"{controllerAction.ControllerName}_{controllerAction.ActionName}";
                }

                // 2. 获取最小 API 的元数据
                var endpointMetadata = apiDesc.ActionDescriptor.EndpointMetadata;
                if (endpointMetadata == null) return null;

                // 3. 提取 EndpointNameMetadata 中定义的操作名称
                var nameMetadata = endpointMetadata.OfType<EndpointNameMetadata>().FirstOrDefault();
                if (nameMetadata?.EndpointName is not string operationName || string.IsNullOrEmpty(operationName))
                    return null;

                // 4. 提取 RelativePath 并解析出资源部分（如 menu）
                var relativePath = apiDesc.RelativePath?.TrimStart('/'); // "api/menu/{id}"
                if (string.IsNullOrEmpty(relativePath)) 
                    return null;

                // 假设路径结构为 /api/{resource}/{id} 或 /api/{resource}
                var parts = relativePath.Split('/', StringSplitOptions.RemoveEmptyEntries);

                // 过滤掉 "api" 并取第一个有意义的段作为资源名（如 menu）
                var resourceSegment = parts
                    .Where(p => p != "api" && !p.StartsWith("{")) // 排除占位符如 {id}
                    .FirstOrDefault();

                if (string.IsNullOrEmpty(resourceSegment)) return null;

                // 5. 转换为首字母大写的 PascalCase 格式
                static string ToPascalCase(string input)
                {
                    if (string.IsNullOrEmpty(input)) return input;
                    return char.ToUpperInvariant(input[0]) + input.Substring(1).ToLowerInvariant();
                }

                var capitalizedResource = ToPascalCase(resourceSegment); // Menu

                // 6. 返回最终 operationId：Menu_GetAllMenus
                return $"{capitalizedResource}_{operationName}";
            });

            c.CustomSchemaIds(type => type.FullName);

            const string searchPattern = "*.xml";
            var xmlFiles= new List<string>();

            DirectoryInfo pluginsDir = new DirectoryInfo(CommonHelper.DefaultFileProvider
                .Combine(Environment.CurrentDirectory, $"{BoilerplatePluginDefaults.PathName}"));
            foreach (DirectoryInfo subDir in pluginsDir.GetDirectories())
            {
                string[] filesInSubDir = Directory.GetFiles(subDir.FullName, searchPattern, SearchOption.AllDirectories);
                xmlFiles.AddRange(filesInSubDir);
            }

            var baseDir = AppDomain.CurrentDomain.BaseDirectory;
            var baseXmlFiles = Directory.GetFiles(baseDir, searchPattern, SearchOption.AllDirectories);
            xmlFiles.AddRange(baseXmlFiles);
            foreach (var xmlFile in xmlFiles)
            {
                c.IncludeXmlComments(xmlFile, true);
            }

            // 添加授权定义
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            });
            c.DocumentFilter<LowerCaseDocumentFilter>();
            // 应用授权要求到操作上
            c.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    },
                    new string[] {}
                }
            });
        });
    }

    public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
    {
        endpointRouteBuilder.MapOpenApi();
    }
}
